#include "Canvas.h"
#include <algorithm>
#include "GlPlatform.h"

Canvas::Canvas() 
	: mViewport(0,0,0,0), mWorldWindow(0,0,0,0) {
}

void Canvas::clear() {
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 
}

void Canvas::present() {
	glFlush(); 
	glutSwapBuffers(); 
}

void Canvas::setup() {
	// Note: Rect::height() assumes world coordinates
	glViewport( mViewport.left, mViewport.bottom, mViewport.width(), mViewport.height() );

	glMatrixMode( GL_PROJECTION ); 
	glLoadIdentity(); 
	glOrtho( mWorldWindow.left, mWorldWindow.right, mWorldWindow.bottom, mWorldWindow.top, -1000, 1000 ); 
	
	glMatrixMode( GL_MODELVIEW ); 
	glLoadIdentity(); 
}

void Canvas::setViewport( const Rect2i& rect ) {
	mViewport = rect;
}

void Canvas::setWorldWindow( const Rect2& view ) {
	mWorldWindow = view;
}

void Canvas::setWorldWindow( const Point2& focus, double scale, double aspect ) {
	double a = getAspectRatio();
	double w = scale * std::min(1., a);
	double h = scale / std::max(1., a);

	setWorldWindow( Rect2::fromSize( focus.x-w/2, focus.y-h/2, w, h ) );
}


Point2 Canvas::toWorld( const Point2i& pt ) const {
	// return mWorldWindow.corner(0) + (Vector2(mViewport.corner(0) - pt)*mWorldWindow.extents()/Vector2(mViewport.extents()));
	return Point2(
		mWorldWindow.left + (pt.x - mViewport.left) * mWorldWindow.width() / mViewport.width(),
		mWorldWindow.top - (pt.y - mViewport.bottom) * mWorldWindow.height() / mViewport.height()
	);
}


Point2i Canvas::toScreen( const Point2& pt ) const {
	return Point2i(
		mViewport.left + (pt.x - mWorldWindow.left) * mViewport.width() / mWorldWindow.width(),
		mViewport.top - (pt.y - mWorldWindow.bottom) * mViewport.height() / mWorldWindow.height()
	);
}


const Rect2i& Canvas::getViewport() const { return mViewport; }
const Rect2& Canvas::getWorldWindow() const { return mWorldWindow; }
double Canvas::getAspectRatio() const {
	return mViewport.width() / (double)mViewport.height();
}
